﻿using System.Net.Http.Headers;
using System.Net;
using HCMS.Extensions;
using HCMS.Utils;
using Newtonsoft.Json;

namespace HCMS.Upload.Util
{
    /// <summary>
    /// 上传 公共处理
    /// </summary>
    public class UploadUtil
    {
        /// <summary>
        /// 上传
        /// </summary>
        /// <param name="files">上传文件列表</param>
        /// <param name="webRootPath">网站根路径</param>
        /// <param name="fileType">上传文件类型</param>
        /// <returns></returns>
        public UploadResult UploadHandle(List<IFormFile> files, string webRootPath, UploadFileType fileType)
        {
            var result = new UploadResult();
            try
            {
                if (files == null || files.Count == 0)
                {
                    throw new UserFriendlyException("没有文件");
                }

                var resultUrl = new List<string>();

                foreach (var file in files)
                {
                    var monryStream = new MemoryStream();
                    file.OpenReadStream().CopyTo(monryStream);
                    var data = monryStream.ToArray();

                    // 1、校验后缀名
                    if (!new UploadCommon().CheckFileTypeByExtName(file.FileName, fileType))
                    {
                        throw new UserFriendlyException("不允许的文件格式");
                    }
                    // 2、校验文件大小
                    if (!new UploadCommon().CheckFileSize(data.Length))
                    {
                        throw new UserFriendlyException("文件大小超出服务器限制");
                    }

                    string imgUrl = string.Empty;
                    // 没有配置上传地址，默认直接上传到本地
                    string remoteUploadUrl = ConfigUtil.GetValue("UploadUrl");
                    if (string.IsNullOrWhiteSpace(remoteUploadUrl))
                    {
                        imgUrl = SaveLocal(data, file.FileName, webRootPath, fileType);
                    }
                    else
                    {
                        imgUrl = SaveRemote(data, file.FileName, remoteUploadUrl, fileType);
                    }

                    resultUrl.Add(imgUrl);
                }
                if (resultUrl.Count > 0)
                {
                    result.url = string.Join(",", resultUrl);
                    result.success = true;
                }
            }
            catch (UserFriendlyException ufe)
            {
                result.errorMsg = ufe.Message;
            }
            catch (Exception ex)
            {
                result.errorMsg = "文件访问出错，请检查写入权限";
            }
            return result;
        }

        //----------------------- 私有方法 -------------------------

        #region SaveLocalHost 保存到本地服务器
        /// <summary>
        /// 保存到本地服务器
        /// </summary>
        /// <param name="bytes">上传文件的字节信息</param>
        /// <param name="fileName">上传文件名</param>
        /// <param name="webRootPath">服务器根路径</param>
        /// <param name="fileType">文件类型</param>
        /// <returns>上传后的文件路径</returns>
        private string SaveLocal(byte[] bytes, string fileName, string webRootPath, UploadFileType fileType)
        {
            var fileImgEx = new UploadCommon.FileExtension[] {
                UploadCommon.FileExtension.BMP, UploadCommon.FileExtension.GIF, UploadCommon.FileExtension.JPG,
                UploadCommon.FileExtension.PNG, UploadCommon.FileExtension.XML, UploadCommon.FileExtension.MP4 };
            var fileDocEx = new UploadCommon.FileExtension[] {
                UploadCommon.FileExtension.TXT, UploadCommon.FileExtension.DOC, UploadCommon.FileExtension.DOCX,
                UploadCommon.FileExtension.XLS, UploadCommon.FileExtension.XLSX, UploadCommon.FileExtension.PPT,
                UploadCommon.FileExtension.PPTX, UploadCommon.FileExtension.PPT };

            var relFileType = "";

            // 判断文件类型【文件字节序列校验】
            if (fileType == UploadFileType.Imgs && !new UploadCommon().IsAllowedExtension(bytes, fileImgEx, out relFileType))
            {
                throw new UserFriendlyException("文件类型不是指定的图片格式");
            }
            else if (fileType == UploadFileType.Doc && !new UploadCommon().IsAllowedExtension(bytes, fileDocEx, out relFileType))
            {
                throw new UserFriendlyException("文件类型不是指定的文档格式");
            }

            var savePath = new UploadCommon().ImgSaveUrl();
            if (fileType == UploadFileType.Doc)
            {
                savePath = new UploadCommon().DocSaveUrl();
            }

            var fileExt = Path.GetExtension(fileName).ToLower();
            fileExt = string.IsNullOrWhiteSpace(fileExt) ? $".{relFileType}" : fileExt;

            // 创建保存的目录
            var realPath = $"{webRootPath}{savePath}";
            if (!Directory.Exists(realPath))
            {
                Directory.CreateDirectory(realPath);
            }

            // 生成新的文件名
            var newFileName = Guid.NewGuid().ToString("N") + fileExt;
            savePath = $"{savePath}{newFileName}";
            realPath = $"{realPath}{newFileName}";

            // 保存文件
            File.WriteAllBytes(realPath, bytes);

            return savePath;
        }
        #endregion

        #region SaveRemote 保存到远程服务器
        /// <summary>
        /// 保存到远程服务器
        /// </summary>
        /// <param name="bytes">上传文件的字节信息</param>
        /// <param name="fileName">上传文件名</param>
        /// <param name="remoteUploadUrl">远程服务器路径</param>
        /// <param name="fileType">文件类型</param>
        /// <returns>上传后的文件路径</returns>
        public string SaveRemote(byte[] bytes, string fileName, string remoteUploadUrl, UploadFileType fileType)
        {
            string imgUrl = string.Empty;

            var fileImgEx = new UploadCommon.FileExtension[] {
                UploadCommon.FileExtension.BMP, UploadCommon.FileExtension.GIF, UploadCommon.FileExtension.JPG,
                UploadCommon.FileExtension.PNG, UploadCommon.FileExtension.XML, UploadCommon.FileExtension.MP4 };
            var fileDocEx = new UploadCommon.FileExtension[] {
                UploadCommon.FileExtension.TXT, UploadCommon.FileExtension.DOC, UploadCommon.FileExtension.DOCX,
                UploadCommon.FileExtension.XLS, UploadCommon.FileExtension.XLSX, UploadCommon.FileExtension.PPT,
                UploadCommon.FileExtension.PPTX, UploadCommon.FileExtension.PPT };

            var relFileType = "";

            // 判断文件类型【文件字节序列校验】
            if (fileType == UploadFileType.Imgs && !new UploadCommon().IsAllowedExtension(bytes, fileImgEx, out relFileType))
            {
                throw new UserFriendlyException("文件类型不是指定的图片格式");
            }
            else if (fileType == UploadFileType.Doc && !new UploadCommon().IsAllowedExtension(bytes, fileDocEx, out relFileType))
            {
                throw new UserFriendlyException("文件类型不是指定的文档格式");
            }

            var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip };
            //创建HttpClient（注意传入HttpClientHandler）
            using (var http = new HttpClient(handler))
            {
                http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));//设定要响应的数据格式       
                using (var content = new MultipartFormDataContent())
                {
                    var fileContent = new ByteArrayContent(bytes);
                    fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                    {
                        Name = "files",
                        FileName = fileName
                    };
                    content.Add(fileContent);

                    HttpResponseMessage response = http.PostAsync(remoteUploadUrl, content).Result;

                    if (!response.IsSuccessStatusCode)
                    {
                        throw new UserFriendlyException($"上传发生异常，状态码：[{(int)response.StatusCode}]");
                    }

                    var resResultStr = response.Content.ReadAsStringAsync().Result;
                    if (resResultStr == null || string.IsNullOrWhiteSpace(resResultStr))
                    {
                        throw new UserFriendlyException("上传接口返回空，上传失败");
                    }

                    var resResult = JsonConvert.DeserializeObject<UploadRemoteResult>(resResultStr);

                    // 上传成功
                    if (resResult != null && resResult.success && resResult.message == "ok" && resResult.data != null && resResult.data.Length > 0)
                    {
                        //Uri uri = new Uri(remoteUploadUrl);
                        //var domain = remoteUploadUrl.Replace(uri.AbsolutePath, "");
                        var domain = "";
                        imgUrl = string.Join(",", resResult.data.Select(t => $"{domain}{t}"));
                    }
                    else
                    {
                        throw new UserFriendlyException($"上传失败，接口返回消息【{resResult.message}】");
                    }
                }
            }

            return imgUrl;
        }
        #endregion
    }

    /// <summary>
    /// 上传结果
    /// </summary>
    public class UploadResult
    {
        /// <summary>
        /// 是否成功
        /// </summary>
        public bool success { get; set; }

        /// <summary>
        /// 上传后的文件路径
        /// </summary>
        public string url { get; set; } = "";

        /// <summary>
        /// 异常消息
        /// </summary>
        public string errorMsg { get; set; } = "";
    }

    /// <summary>
    /// 上传到远程服务器 返回结果
    /// </summary>
    public class UploadRemoteResult
    {
        /// <summary>
        /// 是否成功
        /// </summary>
        public bool success { get; set; }

        /// <summary>
        /// 状态消息
        /// </summary>
        public string message { get; set; } = "";

        /// <summary>
        /// 返回数据信息
        /// </summary>
        /// <remarks>
        /// 文件路径数组
        /// </remarks>
        public string[] data { get; set; }
    }
}

